import React, { useState, useRef, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { Progress } from '@/components/ui/progress';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { X, Upload, File, Folder, CheckCircle, AlertCircle } from 'lucide-react';
import { toast } from 'sonner';
import SparkMD5 from 'spark-md5';

// 上传状态枚举
enum UploadStatus {
  PENDING = 'pending',
  CALCULATING_MD5 = 'calculating_md5',
  CHECKING_MD5 = 'checking_md5',
  UPLOADING = 'uploading',
  SUCCESS = 'success',
  ERROR = 'error'
}

// 文件上传项接口
interface UploadItem {
  id: string;
  file: File;
  name: string;
  size: number;
  type: string;
  relativePath?: string; // 文件夹上传时的相对路径
  md5?: string;
  status: UploadStatus;
  progress: number;
  speed: number; // 上传速度 (bytes/s)
  error?: string;
  canInstant?: boolean; // 是否可以秒传
}

// 组件属性接口
interface FileUploaderProps {
  currentFolderId?: number;
  onUploadComplete?: (files: UploadItem[]) => void;
  onClose?: () => void;
}

// MD5计算函数
const calculateFileMD5 = (file: File, onProgress?: (progress: number) => void): Promise<string> => {
  return new Promise((resolve, reject) => {
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();
    const chunkSize = 2097152; // 2MB chunks
    let currentChunk = 0;
    const chunks = Math.ceil(file.size / chunkSize);

    fileReader.onload = (e) => {
      if (e.target?.result) {
        spark.append(e.target.result as ArrayBuffer);
        currentChunk++;
        
        const progress = Math.round((currentChunk / chunks) * 100);
        onProgress?.(progress);

        if (currentChunk < chunks) {
          loadNext();
        } else {
          resolve(spark.end());
        }
      }
    };

    fileReader.onerror = () => {
      reject(new Error('文件读取失败'));
    };

    const loadNext = () => {
      const start = currentChunk * chunkSize;
      const end = Math.min(start + chunkSize, file.size);
      fileReader.readAsArrayBuffer(file.slice(start, end));
    };

    loadNext();
  });
};

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

// 格式化上传速度
const formatSpeed = (bytesPerSecond: number): string => {
  return formatFileSize(bytesPerSecond) + '/s';
};

// 生成唯一ID
const generateId = (): string => {
  return Date.now().toString(36) + Math.random().toString(36).substr(2);
};

const FileUploader: React.FC<FileUploaderProps> = ({
  currentFolderId,
  onUploadComplete,
  onClose
}) => {
  const [uploadItems, setUploadItems] = useState<UploadItem[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const [isDragOver, setIsDragOver] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const folderInputRef = useRef<HTMLInputElement>(null);

  // 处理文件选择
  const handleFileSelect = useCallback((files: FileList | null, isFolder = false) => {
    if (!files || files.length === 0) return;

    const newItems: UploadItem[] = [];
    
    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      const item: UploadItem = {
        id: generateId(),
        file,
        name: file.name,
        size: file.size,
        type: file.type,
        relativePath: isFolder ? (file as any).webkitRelativePath : undefined,
        status: UploadStatus.PENDING,
        progress: 0,
        speed: 0
      };
      newItems.push(item);
    }

    setUploadItems(prev => [...prev, ...newItems]);
  }, []);

  // 移除上传项
  const removeItem = useCallback((id: string) => {
    setUploadItems(prev => prev.filter(item => item.id !== id));
  }, []);

  // 处理拖拽事件
  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(true);
  }, []);

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);
  }, []);

  const handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);
    
    const files = e.dataTransfer.files;
    handleFileSelect(files);
  }, [handleFileSelect]);

  // 检查MD5秒传
  const checkMD5Upload = async (item: UploadItem): Promise<boolean> => {
    try {
      const { apiClient } = await import('@/lib/api');
      const response = await apiClient.post('/netdisk/upload/check', {
        md5: item.md5,
        filename: item.name,
        fileSize: item.size,
        parentId: currentFolderId
      });

      const result = response.data;
      return result.success && result.data.canInstant;
    } catch (error) {
      console.error('检查MD5失败:', error);
      return false;
    }
  };

  // 实际文件上传
  const uploadFile = async (item: UploadItem): Promise<void> => {
    const formData = new FormData();
    formData.append('file', item.file);
    if (currentFolderId) {
      formData.append('parentId', currentFolderId.toString());
    }
    if (item.md5) {
      formData.append('md5', item.md5);
    }

    const xhr = new XMLHttpRequest();
    const startTime = Date.now();
    let lastLoaded = 0;

    return new Promise((resolve, reject) => {
      xhr.upload.onprogress = (e) => {
        if (e.lengthComputable) {
          const progress = Math.round((e.loaded / e.total) * 100);
          const currentTime = Date.now();
          const timeDiff = (currentTime - startTime) / 1000;
          const speed = timeDiff > 0 ? (e.loaded - lastLoaded) / timeDiff : 0;
          lastLoaded = e.loaded;

          setUploadItems(prev => prev.map(prevItem => 
            prevItem.id === item.id 
              ? { ...prevItem, progress, speed }
              : prevItem
          ));
        }
      };

      xhr.onload = () => {
        if (xhr.status === 200) {
          try {
            const result = JSON.parse(xhr.responseText);
            if (result.success) {
              resolve();
            } else {
              reject(new Error(result.message || '上传失败'));
            }
          } catch (error) {
            reject(new Error('响应解析失败'));
          }
        } else {
          reject(new Error(`上传失败: ${xhr.status}`));
        }
      };

      xhr.onerror = () => {
        reject(new Error('网络错误'));
      };

      xhr.open('POST', 'http://localhost:5000/api/netdisk/upload');
      xhr.setRequestHeader('Authorization', `Bearer ${localStorage.getItem('access_token')}`);
      xhr.send(formData);
    });
  };

  // 处理单个文件上传
  const processUploadItem = async (item: UploadItem): Promise<void> => {
    try {
      // 1. 计算MD5
      setUploadItems(prev => prev.map(prevItem => 
        prevItem.id === item.id 
          ? { ...prevItem, status: UploadStatus.CALCULATING_MD5, progress: 0 }
          : prevItem
      ));

      const md5 = await calculateFileMD5(item.file, (progress) => {
        setUploadItems(prev => prev.map(prevItem => 
          prevItem.id === item.id 
            ? { ...prevItem, progress }
            : prevItem
        ));
      });

      // 更新MD5
      setUploadItems(prev => prev.map(prevItem => 
        prevItem.id === item.id 
          ? { ...prevItem, md5 }
          : prevItem
      ));

      // 2. 检查秒传
      setUploadItems(prev => prev.map(prevItem => 
        prevItem.id === item.id 
          ? { ...prevItem, status: UploadStatus.CHECKING_MD5, progress: 0 }
          : prevItem
      ));

      const canInstant = await checkMD5Upload({ ...item, md5 });
      
      if (canInstant) {
        // 秒传成功
        setUploadItems(prev => prev.map(prevItem => 
          prevItem.id === item.id 
            ? { 
                ...prevItem, 
                status: UploadStatus.SUCCESS, 
                progress: 100,
                canInstant: true
              }
            : prevItem
        ));
        return;
      }

      // 3. 实际上传
      setUploadItems(prev => prev.map(prevItem => 
        prevItem.id === item.id 
          ? { ...prevItem, status: UploadStatus.UPLOADING, progress: 0 }
          : prevItem
      ));

      await uploadFile({ ...item, md5 });

      // 上传成功
      setUploadItems(prev => prev.map(prevItem => 
        prevItem.id === item.id 
          ? { ...prevItem, status: UploadStatus.SUCCESS, progress: 100 }
          : prevItem
      ));

    } catch (error) {
      // 上传失败
      setUploadItems(prev => prev.map(prevItem => 
        prevItem.id === item.id 
          ? { 
              ...prevItem, 
              status: UploadStatus.ERROR, 
              error: error instanceof Error ? error.message : '上传失败'
            }
          : prevItem
      ));
    }
  };

  // 开始上传
  const startUpload = async () => {
    if (uploadItems.length === 0) {
      toast.error('请先选择文件');
      return;
    }

    setIsUploading(true);

    try {
      // 并发上传（限制并发数为3）
      const concurrency = 3;
      const pendingItems = uploadItems.filter(item => item.status === UploadStatus.PENDING);
      
      for (let i = 0; i < pendingItems.length; i += concurrency) {
        const batch = pendingItems.slice(i, i + concurrency);
        await Promise.all(batch.map(item => processUploadItem(item)));
      }

      // 等待状态更新完成后再统计
      setTimeout(() => {
        setUploadItems(currentItems => {
          const successCount = currentItems.filter(item => item.status === UploadStatus.SUCCESS).length;
          const errorCount = currentItems.filter(item => item.status === UploadStatus.ERROR).length;

          if (errorCount === 0) {
            toast.success(`所有文件上传成功 (${successCount}个)`);
            onUploadComplete?.(currentItems);
          } else {
            toast.warning(`上传完成: 成功${successCount}个，失败${errorCount}个`);
          }
          
          return currentItems;
        });
      }, 100);

    } catch (error) {
      toast.error('上传过程中发生错误');
    } finally {
      setIsUploading(false);
    }
  };

  // 获取状态图标
  const getStatusIcon = (status: UploadStatus, canInstant?: boolean) => {
    switch (status) {
      case UploadStatus.SUCCESS:
        return <CheckCircle className="h-4 w-4 text-green-500" />;
      case UploadStatus.ERROR:
        return <AlertCircle className="h-4 w-4 text-red-500" />;
      case UploadStatus.CALCULATING_MD5:
      case UploadStatus.CHECKING_MD5:
      case UploadStatus.UPLOADING:
        return <div className="h-4 w-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />;
      default:
        return <File className="h-4 w-4 text-gray-400" />;
    }
  };

  // 获取状态文本
  const getStatusText = (item: UploadItem) => {
    switch (item.status) {
      case UploadStatus.CALCULATING_MD5:
        return `计算MD5... ${item.progress}%`;
      case UploadStatus.CHECKING_MD5:
        return '检查秒传...';
      case UploadStatus.UPLOADING:
        return `上传中... ${item.progress}% (${formatSpeed(item.speed)})`;
      case UploadStatus.SUCCESS:
        return item.canInstant ? '秒传成功' : '上传成功';
      case UploadStatus.ERROR:
        return `失败: ${item.error}`;
      default:
        return '等待上传';
    }
  };

  return (
    <div className="w-full space-y-6">
        {/* 拖拽上传区域 */}
        <div 
          className={`border-2 border-dashed rounded-lg p-8 text-center transition-all duration-200 ${
            isDragOver 
              ? 'border-blue-400 bg-blue-50 scale-105' 
              : 'border-gray-300 hover:border-gray-400 hover:bg-gray-50'
          }`}
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onDrop={handleDrop}
        >
          <div className={`transition-all duration-200 ${
            isDragOver ? 'transform scale-110' : ''
          }`}>
            <Upload className={`mx-auto h-16 w-16 mb-4 transition-colors ${
              isDragOver ? 'text-blue-500' : 'text-gray-400'
            }`} />
            <p className={`text-xl font-semibold mb-2 transition-colors ${
              isDragOver ? 'text-blue-700' : 'text-gray-900'
            }`}>
              {isDragOver ? '释放文件开始上传' : '拖拽文件到此处或点击选择'}
            </p>
            <p className="text-sm text-gray-500 mb-6">
              支持多文件和文件夹上传，支持拖拽操作
            </p>
          </div>
          
          <div className="flex justify-center space-x-4">
            <Button 
              onClick={() => fileInputRef.current?.click()}
              disabled={isUploading}
              className="px-6 py-2"
            >
              <File className="mr-2 h-4 w-4" />
              选择文件
            </Button>
            <Button 
              variant="outline" 
              onClick={() => folderInputRef.current?.click()}
              disabled={isUploading}
              className="px-6 py-2"
            >
              <Folder className="mr-2 h-4 w-4" />
              选择文件夹
            </Button>
          </div>
        </div>

        {/* 上传控制按钮 */}
        {uploadItems.length > 0 && (
          <div className="flex justify-end">
            <Button
              onClick={startUpload}
              disabled={uploadItems.length === 0 || isUploading}
            >
              {isUploading ? '上传中...' : '开始上传'}
            </Button>
          </div>
        )}

        {/* 隐藏的文件输入 */}
        <input
          ref={fileInputRef}
          type="file"
          multiple
          className="hidden"
          onChange={(e) => handleFileSelect(e.target.files)}
        />
        <input
          ref={folderInputRef}
          type="file"
          multiple
          webkitdirectory=""
          className="hidden"
          onChange={(e) => handleFileSelect(e.target.files, true)}
        />

        {/* 上传列表 */}
        {uploadItems.length > 0 && (
          <div className="bg-gray-50 rounded-lg p-4 border">
            <div className="flex items-center justify-between mb-4">
              <div className="flex items-center space-x-2">
                <Upload className="h-5 w-5 text-blue-600" />
                <span className="font-semibold">上传队列</span>
                <Badge variant="secondary" className="ml-2">
                  {uploadItems.length} 个文件
                </Badge>
              </div>
              <Button 
                variant="outline" 
                size="sm" 
                onClick={() => setUploadItems(prev => prev.filter(item => 
                  item.status === UploadStatus.UPLOADING || item.status === UploadStatus.CALCULATING_MD5
                ))}
                className="text-xs"
              >
                清除已完成
              </Button>
            </div>
            <div className="space-y-3 max-h-80 overflow-y-auto pr-2">
              {uploadItems.map((item) => (
                <div key={item.id} className="bg-white rounded-lg p-4 border border-gray-200 hover:shadow-md transition-shadow">
                  <div className="flex items-start justify-between mb-3">
                    <div className="flex items-center space-x-3 flex-1 min-w-0">
                      <div className="flex-shrink-0">
                        {getStatusIcon(item.status, item.canInstant)}
                      </div>
                      <div className="flex-1 min-w-0">
                        <p className="text-sm font-medium text-gray-900 truncate" title={item.relativePath || item.name}>
                          {item.relativePath || item.name}
                        </p>
                        <p className="text-xs text-gray-500">
                          {formatFileSize(item.size)}
                          {item.md5 && (
                            <span className="ml-2 font-mono">MD5: {item.md5.substring(0, 8)}...</span>
                          )}
                        </p>
                      </div>
                    </div>
                    <div className="flex items-center space-x-2 flex-shrink-0">
                      <Badge 
                        variant={item.status === UploadStatus.SUCCESS ? 'default' : 
                                item.status === UploadStatus.ERROR ? 'destructive' : 'secondary'}
                        className="text-xs"
                      >
                        {getStatusText(item)}
                      </Badge>
                      {item.status === UploadStatus.PENDING && (
                        <Button
                          variant="ghost"
                          size="sm"
                          onClick={() => removeItem(item.id)}
                          className="h-6 w-6 p-0"
                        >
                          <X className="h-3 w-3" />
                        </Button>
                      )}
                    </div>
                  </div>
                  
                  {/* 进度条 */}
                  {(item.status === UploadStatus.CALCULATING_MD5 || 
                    item.status === UploadStatus.UPLOADING) && (
                    <div className="space-y-2">
                      <Progress 
                        value={item.progress} 
                        className="h-2 bg-gray-200"
                      />
                      <div className="flex justify-between items-center text-xs">
                        <span className="text-gray-600 font-medium">
                          {item.progress.toFixed(1)}%
                        </span>
                        {item.speed > 0 && (
                          <span className="text-blue-600 font-medium">
                            {formatSpeed(item.speed)}
                          </span>
                        )}
                      </div>
                    </div>
                  )}
                </div>
              ))}
            </div>
          </div>
        )}

      {/* 统计信息 */}
      {uploadItems.length > 0 && (
        <div className="text-sm text-gray-500 border-t pt-4 mt-6">
          <div className="flex justify-between items-center">
            <span>
              总计: {uploadItems.length} 个文件，
              大小: {formatFileSize(uploadItems.reduce((sum, item) => sum + item.size, 0))}
            </span>
            <div className="flex space-x-4 text-xs">
              <span className="text-green-600">
                成功: {uploadItems.filter(item => item.status === UploadStatus.SUCCESS).length}
              </span>
              <span className="text-red-600">
                失败: {uploadItems.filter(item => item.status === UploadStatus.ERROR).length}
              </span>
              <span className="text-blue-600">
                进行中: {uploadItems.filter(item => 
                  item.status === UploadStatus.UPLOADING || 
                  item.status === UploadStatus.CALCULATING_MD5 ||
                  item.status === UploadStatus.CHECKING_MD5
                ).length}
              </span>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default FileUploader;